package com.gzxw.mogublog.xo.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gzxw.mogublog.base.global.BaseSysConf;
import com.gzxw.mogublog.base.holder.RequestHolder;
import com.gzxw.mogublog.commons.entity.*;
import com.gzxw.mogublog.commons.feign.PictureFeignClient;
import com.gzxw.mogublog.utils.R;
import com.gzxw.mogublog.utils.RedisUtil;
import com.gzxw.mogublog.utils.StringUtils;
import com.gzxw.mogublog.xo.mapper.BlogMapper;
import com.gzxw.mogublog.xo.service.*;
import com.gzxw.mogublog.xo.vo.BlogVO;
import org.apache.commons.beanutils.BeanMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
@Transactional
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements BlogService {


    @Autowired
    private BlogSortService blogSortService;

    @Autowired
    private TagService tagService;

    @Autowired
    private PictureFeignClient pictureFeignClient;

    @Autowired
    private SysParamsService sysParamsService;

    @Autowired
    private CommentService commentService;

    @Autowired
    private RedisUtil redisUtil;


    @Override
    public IPage<Blog> getPageList(BlogVO blogVO) {

        // 构造查询条件
        QueryWrapper<Blog> queryWrapper = new QueryWrapper<>();
        // 根据title
        if (StringUtils.isNotEmpty(blogVO.getKeyword()) && !StringUtils.isEmpty(blogVO.getKeyword().trim())) {
            queryWrapper.like("title", blogVO.getKeyword().trim());
        }
        // 标签taguid
        if (!StringUtils.isEmpty(blogVO.getTagUid())) {
            queryWrapper.eq("tag_uid", blogVO.getTagUid());
        }
        // 分类iduid
        if (!StringUtils.isEmpty(blogVO.getBlogSortUid())) {
            queryWrapper.eq("blog_sort_uid", blogVO.getBlogSortUid());
        }
        // 推荐等级level
        if (!StringUtils.isEmpty(blogVO.getLevelKeyword())) {
            queryWrapper.eq("level", blogVO.getLevelKeyword());
        }
        // 是否发布ispublish
        if (!StringUtils.isEmpty(blogVO.getIsPublish())) {
            queryWrapper.eq("is_publish", blogVO.getIsPublish());
        }
        // 是否是原创
        if (!StringUtils.isEmpty(blogVO.getIsOriginal())) {
            queryWrapper.eq("is_original", blogVO.getIsOriginal());
        }
        // 博客类型
        if (!StringUtils.isEmpty(blogVO.getType())) {
            queryWrapper.eq("type", blogVO.getType());
        }

        // 分页
        Page<Blog> page = new Page<>();
        page.setCurrent(blogVO.getCurrentPage()); // 设置当前页
        page.setSize(blogVO.getPageSize()); // 设置每页的记录数
        queryWrapper.eq("status", 1);

        // 解决排序
        if (StringUtils.isNotEmpty(blogVO.getOrderByAscColumn())) {
            String orderColumn = StringUtils.underLine(new StringBuffer(blogVO.getOrderByAscColumn())).toString();
            queryWrapper.orderByAsc(orderColumn);
        } else if (StringUtils.isNotEmpty(blogVO.getOrderByDescColumn())) {
            String orderColumn = StringUtils.underLine(new StringBuffer(blogVO.getOrderByDescColumn())).toString();
            queryWrapper.orderByDesc(orderColumn);
        } else {
            // 判断是否启用排序字段
            if (blogVO.getUseSort() == 0) {
                // 如果未使用，则按照创建时间倒序排序
                queryWrapper.orderByDesc("create_time");
            } else {
                // 如果启用了,则默认按sort值大小倒序
                queryWrapper.orderByDesc("sort");
            }
        }

        IPage<Blog> pageList = this.page(page, queryWrapper);

        // 里面Blog的标签和分类属性未赋值
        List<Blog> records = pageList.getRecords();

        if (records.size() == 0) {
            return pageList;
        }

        // 将标题图片id，分类id和标签id取出来
        List<String> sortUids = new ArrayList<>(); // 分类ids
        List<String> tagUids = new ArrayList<>(); //标签ids
        List<String> pictureUids = new ArrayList<>(); //图片fileUids

        records.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getBlogSortUid())) {
                sortUids.add(item.getBlogSortUid());
            }
            if (StringUtils.isNotEmpty(item.getTagUid())) {
                List<String> tagUidsTemp = StringUtils.changeStringToString(item.getTagUid(), ",");
                tagUids.addAll(tagUidsTemp);
            }
            if (StringUtils.isNotEmpty(item.getFileUid())) {
                pictureUids.add(item.getFileUid());
            }
        });


        Collection<BlogSort> sortList = new ArrayList<>();
        Collection<Tag> tagList = new ArrayList<>();
        // 调用图片服务
        R picResult = null;
        if (pictureUids.size() > 0) {
            picResult = pictureFeignClient.getPictures(pictureUids);
        }
        String data = picResult.getMessage();
        List<File> fileList = JSON.parseArray(data, File.class);

        if (sortUids.size() > 0) {
            sortList = blogSortService.listByIds(sortUids);
        }

        if (tagUids.size() > 0) {
            tagList = tagService.listByIds(tagUids);
        }

        Map<String, BlogSort> sortMap = new HashMap<>();
        Map<String, Tag> tagMap = new HashMap<>();
        Map<String, File> fileMap = new HashMap<>();

        sortList.forEach(item -> {
            sortMap.put(item.getUid(), item);
        });

        tagList.forEach(item -> {
            tagMap.put(item.getUid(), item);
        });

        fileList.forEach(item -> {
            fileMap.put(item.getUid(), item);
        });

        // 给Blog设置分类，以及标签
        for (Blog blog : records) {

            if (StringUtils.isNotEmpty(blog.getBlogSortUid())) {
                blog.setBlogSort(sortMap.get(blog.getBlogSortUid()));
            }

            if (StringUtils.isNotEmpty(blog.getTagUid())) {
                List<String> tagUidsTemp = StringUtils.changeStringToString(blog.getTagUid(), ",");
                List<Tag> tags = new ArrayList<>();
                tagUidsTemp.forEach(item -> {
                    tags.add(tagMap.get(item));
                });
                blog.setTagList(tags);
            }

            if (StringUtils.isNotEmpty(blog.getFileUid())) {
                String fileUid = blog.getFileUid();
                File file = fileMap.get(fileUid);
                if (file != null) {
                    String picUrl = file.getPicUrl();
                    blog.setPhotoUrl(picUrl);
                }
            }
        }
        pageList.setRecords(records);
        return pageList;
    }


    @Override
    public String addBlog(BlogVO blogVO) {

        // 此处不判断博客的推荐水平数是否超出

        Blog blog = new Blog();

        blog.setTitle(blogVO.getTitle());
        blog.setSummary(blogVO.getSummary());
        blog.setContent(blogVO.getContent());
        blog.setTagUid(blogVO.getTagUid());
        blog.setBlogSortUid(blogVO.getBlogSortUid());
        blog.setFileUid(blogVO.getFileUid());
        blog.setLevel(blogVO.getLevel());
        blog.setIsOriginal(blogVO.getIsOriginal());
        blog.setIsPublish(blogVO.getIsPublish());
        blog.setType(blogVO.getType());
        blog.setOutsideLink(blogVO.getOutsideLink());
        blog.setStatus(1);
        blog.setOpenComment(blogVO.getOpenComment());

        boolean isSave = this.save(blog);
        //TODO 保存成功后，需要发送消息到solr 和 redis

        return isSave ? "保存成功" : "保存失败";
    }

    @Override
    public String edit(BlogVO blogVO) {

        Blog blog = this.getById(blogVO.getUid());
        blog.setTitle(blogVO.getTitle());
        blog.setSummary(blogVO.getSummary());
        blog.setContent(blogVO.getContent());
        blog.setTagUid(blogVO.getTagUid());
        blog.setBlogSortUid(blogVO.getBlogSortUid());
        blog.setFileUid(blogVO.getFileUid());
        blog.setLevel(blogVO.getLevel());
        blog.setIsOriginal(blogVO.getIsOriginal());
        blog.setIsPublish(blogVO.getIsPublish());
        blog.setOpenComment(blogVO.getOpenComment());
        blog.setUpdateTime(new Date());
        blog.setType(blogVO.getType());
        blog.setOutsideLink(blogVO.getOutsideLink());
        blog.setStatus(1);

        boolean isUpdate = this.updateById(blog);
        //保存成功后，需要发送消息到solr 和 redis
        return isUpdate ? "修改成功" : "修改失败";
    }

    @Override
    public String deleteBlog(BlogVO blogVO) {

        // 1.注意删除博客是逻辑删除,使用更新的方式
        // 2.设置blog的状态为0  0-->删除/停用  1-->启用
        // blog.setStatus(EStatus.DISABLED);
        // 3.blog.updateById();
        //保存成功后，需要发送消息到solr 和 redis, 同时从专题管理Item中移除该博客
        // 4.移除所有包含该博客的专题Item
        // 5.移除该文章下所有评论
        return null;
    }

    @Override
    public IPage<Blog> getBlogPageByLevel(Integer level, Long currentPage, Integer useSort) {

        //从Redis中获取内容
//        String jsonResult = redisUtil.get(RedisConf.BLOG_LEVEL + RedisConf.SEGMENTATION + level);

        Page<Blog> page = new Page<>();
        page.setCurrent(currentPage);
        String blogCount = null; //设置该推荐等级的博客数量（因为每个推荐等级博客数量未必都相等）
        switch (level) {
            case 0: {
                blogCount = sysParamsService.getSysParamsValueByKey(BaseSysConf.BLOG_NEW_COUNT);
            }
            break;
            case 1: {
                blogCount = sysParamsService.getSysParamsValueByKey(BaseSysConf.BLOG_FIRST_COUNT);
            }
            break;
            case 2: {
                blogCount = sysParamsService.getSysParamsValueByKey(BaseSysConf.BLOG_SECOND_COUNT);
            }
            break;
            case 3: {
                blogCount = sysParamsService.getSysParamsValueByKey(BaseSysConf.BLOG_THIRD_COUNT);
            }
            break;
            case 4: {
                blogCount = sysParamsService.getSysParamsValueByKey(BaseSysConf.BLOG_FOURTH_COUNT);
            }
            break;
        }

        if (StringUtils.isEmpty(blogCount)) {
            log.error("请先到后台配置相关参数");
        } else {
            assert blogCount != null;
            page.setSize(Long.parseLong(blogCount));
        }

        QueryWrapper<Blog> blogQueryWrapper = new QueryWrapper<>();
        blogQueryWrapper.eq("status", 1);
        blogQueryWrapper.eq("level", level);
        blogQueryWrapper.eq("is_publish", 1);

        if (useSort == 1) {
            blogQueryWrapper.orderByDesc("sort");
        } else {
            blogQueryWrapper.orderByDesc("create_time");
        }

        // 排除内容
        blogQueryWrapper.select(Blog.class, item -> !item.getProperty().equals("content"));

        IPage<Blog> pageList = this.page(page, blogQueryWrapper);
        List<Blog> records = pageList.getRecords();

        // 一级推荐或者二级推荐没有内容时，自动把top5填充至一级推荐和二级推荐中

        if ((level == 1 || level == 2) && records.size() <= 0) {
            QueryWrapper<Blog> queryWrapper = new QueryWrapper<>();
            Page<Blog> hotPage = new Page<>();
            hotPage.setCurrent(1);
            String blogHotCount = sysParamsService.getSysParamsValueByKey(BaseSysConf.BLOG_HOT_COUNT);
            String blogSecondCount = sysParamsService.getSysParamsValueByKey(BaseSysConf.BLOG_SECOND_COUNT);
            if (StringUtils.isEmpty(blogHotCount) || StringUtils.isEmpty(blogSecondCount)) {
                log.error("请配置参数");
            } else {
                hotPage.setSize(Long.valueOf(blogHotCount));
            }

            queryWrapper.eq("status", 1);
            queryWrapper.eq("is_publish", 1);
            queryWrapper.orderByDesc("click_count"); // 按照点击量来排序
            queryWrapper.select(Blog.class, i -> !i.getProperty().equals("content"));

            IPage<Blog> hotPageList = this.page(hotPage, queryWrapper);
            List<Blog> hotBlogList = hotPageList.getRecords();

            List<Blog> secondBlogList = new ArrayList<>();
            List<Blog> firstBlogList = new ArrayList<>();

            for (int a = 0; a < hotBlogList.size(); a++) {
                // 当推荐大于两个的时候
                if ((hotBlogList.size() - firstBlogList.size()) > Long.valueOf(blogSecondCount)) {
                    firstBlogList.add(hotBlogList.get(a));
                } else {
                    secondBlogList.add(hotBlogList.get(a));
                }
            }

            setBlog(firstBlogList);
            setBlog(secondBlogList);

            switch (level) {
                case 1: {
                    pageList.setRecords(firstBlogList);
                }
                break;
                case 2: {
                    pageList.setRecords(secondBlogList);
                }
                break;
            }
        } else {
            setBlog(records);
        }

        return pageList;
    }

    @Override
    public IPage<Blog> getNewBlog(Long currentPage, Long pageSize) {
        String blogNewCount = sysParamsService.getSysParamsValueByKey(BaseSysConf.BLOG_NEW_COUNT);
        if (StringUtils.isEmpty(blogNewCount)) {
            log.error("参数配置有误");
        }

        QueryWrapper<Blog> queryWrapper = new QueryWrapper<>();
        Page<Blog> page = new Page<>();
        page.setCurrent(currentPage);
        page.setSize(Long.valueOf(blogNewCount));
        queryWrapper.eq("status", 1);
        queryWrapper.eq("is_publish", 1);
        queryWrapper.orderByDesc("create_time");

        //因为首页并不需要显示内容，所以需要排除掉内容字段
        queryWrapper.select(Blog.class, i -> !i.getProperty().equals("content"));

        IPage<Blog> pageList = this.page(page, queryWrapper);
        List<Blog> list = pageList.getRecords();

        if (list.size() <= 0) {
            return pageList;
        }

        setBlog(list);
        pageList.setRecords(list);

        return pageList;
    }

    @Override
    public Integer getBlogPraiseCountByUid(String uid) {

        Integer pariseCount = 0;
        if (StringUtils.isEmpty(uid)) {
            log.error("传入的UID为空");
            return pariseCount;
        }

        // 从redis中取出点赞数
        String praiseResult = redisUtil.get("BLOG_PRAISE" + ":" + uid);
        if (!StringUtils.isEmpty(praiseResult)) {
            pariseCount = Integer.parseInt(praiseResult);
        }
        return pariseCount;
    }

    @Override
    public String praiseBlogByUid(String uid) {
        if (StringUtils.isEmpty(uid)) {
            return "参数不正确";
        }

        HttpServletRequest request = RequestHolder.getRequest();

//        Object adminUidObj = request.getAttribute("adminUid");

//            String userUid = request.getAttribute("adminUid").toString();
        String userUid = "3124514bff8a925fc77a5828a9ebcdbd";
            // TODO 判断点赞时是否已经登录

            QueryWrapper<Comment> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_uid", userUid);
            queryWrapper.eq("blog_uid", uid);
            queryWrapper.eq("type", 1);
            queryWrapper.last("limit 1");
            Comment praise = commentService.getOne(queryWrapper);
            if (praise != null) {
                return "您已经点赞过了";
            }


        Blog blog = this.getById(uid);
        String pariseJsonResult = redisUtil.get("BLOG_PARAISE" + ":" + uid);
        if (pariseJsonResult == null) {
            // 说明从未有人点过赞
            redisUtil.set("BLOG_PARAISE" + ":" + uid,"1");
            blog.setCollectCount(1);
            blog.updateById();
        }else {
            Integer collectCount = blog.getCollectCount() + 1;
            // 博客点赞数+1
            redisUtil.set("BLOG_PARAISE" + ":" + uid,collectCount.toString());
            blog.setCollectCount(collectCount);
            blog.updateById();
        }

        // 已登录用户，向评论表添加点赞数据
//        String adminUid = adminUidObj.toString();
        Comment comment = new Comment();
        comment.setUserUid(userUid);
        comment.setBlogUid(uid);
        comment.setType(1);
        comment.setSource("BLOG_INFO");
        comment.insert();

        return "点赞成功";
    }

    @Override
    public IPage<Blog> getSameBlogByTagUid(String tagUid) {

        QueryWrapper<Blog> queryWrapper = new QueryWrapper<>();
        Page<Blog> page = new Page<>();
        page.setCurrent(1);
        page.setSize(10);
        queryWrapper.like("tag_uid", tagUid);
        queryWrapper.orderByDesc("create_time");
        queryWrapper.eq("status", 1);
        queryWrapper.eq("is_publish", 1);
        IPage<Blog> pageList = this.page(page, queryWrapper);
        List<Blog> list = pageList.getRecords();
        list = this.setTagAndSortByBlogList(list);
        pageList.setRecords(list);

        return pageList;
    }

    /**
     * 给博客列表设置分类和标签
     *
     * @param list
     * @return
     */
    @Override
    public List<Blog> setTagAndSortByBlogList(List<Blog> list) {

        List<String > sortUids = new ArrayList<>();
        List<String > tagUids = new ArrayList<>();

        list.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getBlogSortUid())) {
                sortUids.add(item.getBlogSortUid());
            }
            if (StringUtils.isNotEmpty(item.getTagUid())) {
                String[] tagList = item.getTagUid().split(",");
                tagUids.addAll(Arrays.asList(tagList));
            }
        });

        Collection<BlogSort> blogSorts = blogSortService.listByIds(sortUids);
        Collection<Tag> tags = tagService.listByIds(tagUids);

        Map<String ,BlogSort> sortMap = new HashMap<>();
        Map<String ,Tag> tagMap = new HashMap<>();

        blogSorts.forEach(item -> {
            sortMap.put(item.getUid(),item);
        });

        tags.forEach(item -> {
            tagMap.put(item.getUid(),item);
        });

        list.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getBlogSortUid())) {
                item.setBlogSort(sortMap.get(item.getBlogSortUid()));
            }
            if (StringUtils.isNotEmpty(item.getTagUid())) {
                List<Tag> tagList = new ArrayList<>();
                String[] tagUidList = item.getTagUid().split(",");
                for (String tagUid : tagUidList) {
                    tagList.add(tagMap.get(tagUid));
                }
                item.setTagList(tagList);
            }
        });

        return list;
    }

    @Override
    public IPage<Blog> getSameBlogByBlogUid(String blogUid) {

        Blog blog = this.getById(blogUid);
        QueryWrapper<Blog> blogQueryWrapper = new QueryWrapper<>();
        blogQueryWrapper.eq("status",1);
        Page<Blog> page = new Page<>();
        page.setCurrent(1);
        page.setSize(10);

        String blogSortUid = blog.getBlogSortUid();
        blogQueryWrapper.eq("blog_sort_uid",blogSortUid);
        blogQueryWrapper.eq("is_publish",1);
        blogQueryWrapper.orderByDesc("create_time");
        IPage<Blog> pageList = this.page(page, blogQueryWrapper);
        List<Blog> records = pageList.getRecords();
        records =setTagAndSortByBlogList(records);

        //过滤掉当前的博客
        List<Blog> newList = new ArrayList<>();

        for (Blog record : records) {
            if (!blogUid.equals(record.getUid())) {
                continue;
            }
            newList.add(record);
        }
        pageList.setRecords(newList);
        return pageList;
    }

    /**
     * 设置博客的分类标签和内容
     *
     * @param list
     * @return
     */
    private List<Blog> setBlog(List<Blog> list) {
        List<String> sortUids = new ArrayList<>();
        List<String> tagUids = new ArrayList<>();
        List<String> picUids = new ArrayList<>();

        list.forEach(item -> {

            if (StringUtils.isNotEmpty(item.getBlogSortUid())) {
                sortUids.add(item.getBlogSortUid());
            }
            if (StringUtils.isNotEmpty(item.getTagUid())) {
                tagUids.add(item.getTagUid());
            }
            if (StringUtils.isNotEmpty(item.getFileUid())) {
                picUids.add(item.getFileUid());
            }
        });

        Collection<BlogSort> sortList = new ArrayList<>();
        Collection<Tag> tagList = new ArrayList<>();
        List<File> fileList = new ArrayList<>();

        if (sortUids.size() > 0) {
            sortList = blogSortService.listByIds(sortUids);
        }
        if (tagUids.size() > 0) {
            tagList = tagService.listByIds(tagUids);
        }
        // 调用图片服务
        if (picUids.size() > 0) {
            R picResult = pictureFeignClient.getPictures(picUids);
            String message = picResult.getMessage();
            fileList = JSON.parseArray(message, File.class);
        }

        Map<String, BlogSort> sortMap = new HashMap<>();
        Map<String, Tag> tagMap = new HashMap<>();
        Map<String, String> fileMap = new HashMap<>();

        sortList.forEach(item -> {
            sortMap.put(item.getUid(), item);
        });

        tagList.forEach(item -> {
            tagMap.put(item.getUid(), item);
        });

        fileList.forEach(item -> {
            fileMap.put(item.getUid(), item.getPicUrl());
        });

        for (Blog item : list) {

            //设置分类
            if (StringUtils.isNotEmpty(item.getBlogSortUid())) {
                item.setBlogSort(sortMap.get(item.getBlogSortUid()));
            }

            //获取标签
            if (StringUtils.isNotEmpty(item.getTagUid())) {
                List<String> tagUidsTemp = StringUtils.changeStringToString(item.getTagUid(), BaseSysConf.FILE_SEGMENTATION);
                List<Tag> tagListTemp = new ArrayList<Tag>();

                tagUidsTemp.forEach(tag -> {
                    if (tagMap.get(tag) != null) {
                        tagListTemp.add(tagMap.get(tag));
                    }
                });
                item.setTagList(tagListTemp);
            }

            // 获取图片
            if (StringUtils.isNotEmpty(item.getFileUid())) {
                String photoUrl = fileMap.get(item.getFileUid());
                item.setPhotoUrl(photoUrl);
                item.setPhotoList(Collections.singletonList(photoUrl));
            }

        }

        return list;
    }

    @Override
    public Blog setTagByBlog(Blog blog) {

        String tagUid = blog.getTagUid();
        if (!StringUtils.isEmpty(tagUid)) {
            String[] uids = tagUid.split(",");
            List<Tag> tagList = new ArrayList<>();
            for (String uid : uids) {
                Tag tag = tagService.getById(uid);
                if (tag != null && tag.getStatus() != 0) {
                    tagList.add(tag);
                }
            }
            blog.setTagList(tagList);
        }
        return blog;
    }

    @Override
    public Blog setSortByBlog(Blog blog) {
        if (blog != null && !StringUtils.isEmpty(blog.getBlogSortUid())) {
            BlogSort blogSort = blogSortService.getById(blog.getBlogSortUid());
            blog.setBlogSort(blogSort);
        }
        return blog;
    }
}
